package cn.duckerkj.gzip;

import java.io.*;

import javax.servlet.*;
import javax.servlet.http.*;



/**
 * This class is used for wrapped response for getting cached data.
 *
 * @author Shensg
 */
public class CachedResponseWrapper extends HttpServletResponseWrapper {

	/**
	 * Indicate that getOutputStream() or getWriter() is not called yet.
	 */
	public static final int OUTPUT_NONE = 0;

	/**
	 * Indicate that getWriter() is already called.
	 */
	public static final int OUTPUT_WRITER = 1;

	/**
	 * Indicate that getOutputStream() is already called.
	 */
	public static final int OUTPUT_STREAM = 2;

	private int outputType = OUTPUT_NONE;

	private int status = SC_OK;
	private ServletOutputStream output = null;
	private PrintWriter writer = null;
	private ByteArrayOutputStream buffer = null;

	public CachedResponseWrapper(HttpServletResponse resp) throws IOException {
		super(resp);
		buffer = new ByteArrayOutputStream();
	}

	public int getStatus() {
		return status;
	}

	public void setStatus(int status) {
		super.setStatus(status);
		this.status = status;
	}

	public void setStatus(int status, String string) {
		/*super.setStatus(status, string);*/
		super.setStatus(status);
		this.status = status;
	}

	public void sendError(int status, String string) throws IOException {
		super.sendError(status, string);
		this.status = status;
	}

	public void sendError(int status) throws IOException {
		super.sendError(status);
		this.status = status;
	}

	public void sendRedirect(String location) throws IOException {
		super.sendRedirect(location);
		this.status = SC_MOVED_TEMPORARILY;
	}

	public PrintWriter getWriter() throws IOException {
		if (outputType == OUTPUT_STREAM)
			throw new IllegalStateException();
		else if (outputType == OUTPUT_WRITER)
			return writer;
		else {
			outputType = OUTPUT_WRITER;
			writer = new PrintWriter(new OutputStreamWriter(buffer, getCharacterEncoding()));
			return writer;
		}
	}

	public ServletOutputStream getOutputStream() throws IOException {
		if (outputType == OUTPUT_WRITER)
			throw new IllegalStateException();
		else if (outputType == OUTPUT_STREAM)
			return output;
		else {
			outputType = OUTPUT_STREAM;
			output = new WrappedOutputStream(buffer);
			return output;
		}
	}

	public void flushBuffer() throws IOException {
		if (outputType == OUTPUT_WRITER)
			writer.flush();
		if (outputType == OUTPUT_STREAM)
			output.flush();
	}

	public void reset() {
		outputType = OUTPUT_NONE;
		buffer.reset();
	}

	/**
	 * Call this method to get cached response data.
	 * 
	 * @return byte array buffer.
	 * @throws IOException
	 */
	public byte[] getResponseData() throws IOException {
		flushBuffer();
		return buffer.toByteArray();
	}

	/**
	 * This class is used to wrap a ServletOutputStream and store output stream in
	 * byte[] buffer.
	 */
	class WrappedOutputStream extends ServletOutputStream {

		private ByteArrayOutputStream buffer;

		public WrappedOutputStream(ByteArrayOutputStream buffer) {
			this.buffer = buffer;
		}

		public void write(int b) throws IOException {
			buffer.write(b);
		}

		public byte[] toByteArray() {
			return buffer.toByteArray();
		}

		@Override
		public boolean isReady() {
			// TODO Auto-generated method stub
			return false;
		}

		@Override
		public void setWriteListener(WriteListener writeListener) {
			// TODO Auto-generated method stub
			
		}
	}
/**
 * 调用方式
 * 在filter中直接使用
 * filterchain.doFilter(request, wrapper);
				 // 首先判断status, 只对200状态处理：
				 if(wrapper.getStatus()==HttpServletResponse.SC_OK) {
					 // 对响应进行处理，这里是进行GZip压缩:
					 byte[] data = GzipUtils.gzip(wrapper.getResponseData());
					 response.setContentType(wrapper.getContentType());
					 response.setContentLength(data.length);
					 response.setHeader("Content-Encoding", "gzip");
					 ServletOutputStream output = response.getOutputStream();
					 output.write(data);
					 output.flush();
				 }
 */
}